<?php

class Crypto extends UserLib
{
	public static function genKey( $userName, $passwd )
	{
		$userName = self::mixData($userName, 7);
		$passwd = self::mixData($passwd, 9);
		$key = sha1($userName . $passwd);

		return($key);
	}

	public static function mixData( $data, $level )
	{
		if ( !$level )
			$level = self::getLevel($data);

		$data = self::padData($data, $level);
		$cols = strlen($data) / $level;
		$in = str_split($data);
		$out = array();
		$pos = 0;

		for ( $i = 0; $i < $level; $i++ ){
			for ( $ind = 0; $ind < $cols; $ind++ ){
				$out[$pos] = $in[($ind * $level) + $i];
				$pos++;
			}
		}
		$out = join($out) . "l-$level";

		return($out);
	}

	public static function encrypt( $data, $key )
	{
		self::randomize();

		$key = md5($key);

		$td = mcrypt_module_open('rijndael-256', '','cbc', '');
		$key = substr($key, 0, mcrypt_enc_get_key_size($td));
		$iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($td), MCRYPT_RAND);

		if (mcrypt_generic_init($td, $key, $iv) != -1) {
			$encrypted = mcrypt_generic($td, $data);
			mcrypt_generic_deinit($td);
			mcrypt_module_close($td);

			$encrypted = $iv . $encrypted;

			return($encrypted);
		}

		return(false);
	}

	public static function decrypt( $data, $key )
	{
		if ( !$data || !$key )
			return;

		$key = md5($key);

		$td = mcrypt_module_open('rijndael-256', '','cbc', '');
		$key = substr($key, 0, mcrypt_enc_get_key_size($td));
		$iv_size = mcrypt_enc_get_iv_size($td);
		$iv = substr($data, 0, $iv_size);
		$string = substr($data, $iv_size);

		if (mcrypt_generic_init($td, $key, $iv) != -1) {
			$decrypted = mdecrypt_generic($td, $data);

			mcrypt_generic_deinit($td);
			mcrypt_module_close($td);

			return (substr(trim($decrypted), $iv_size));
		}

		return(false);
	}

	public static function randomize()
	{
		srand((double) microtime() * 1000000);
	}

	private static function getLevel($data)
	{
		$len = strlen($data);
		$level = 1;

		while ( $level % 2 ) {
			$level = rand(2, $len / 2);
		}

		return($level);
	}

	private static function padData($data, $level)
	{
		$padding = 1;

		while ( (strlen($data) + $padding) % $level){
			$padding++;
		}

		$data = $data . str_repeat("-", $padding);

		return($data);
	}

	public static function getInstance()
	{
		if ( !self::$instance )
			self::$instance = new Crypto();

		return( self::$instance );
	}
}
?>
